#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>

void *thread_run(void *arg)
{
    pthread_detach(pthread_self()); // 自主分离
    printf("%s\n", (char *)arg);
    return NULL;
}

int main(void)
{
    pthread_t tid;
    if (pthread_create(&tid, NULL, thread_run, "thread1 run...") != 0)
    {
        printf("create thread error\n");
        return 1;
    }

    int ret = 0;
    //sleep(1); // 很重要，要让线程先分离，再等待
    if (pthread_join(tid, NULL) == 0)
    {
        printf("pthread wait success\n");
        ret = 0;
    }
    else
    {
        printf("pthread wait failed\n");
        ret = 1;
    }

    return ret;
}

// #include <stdio.h>
// #include <stdlib.h>
// #include <string.h>
// #include <unistd.h>
// #include <pthread.h>
// void *thread1(void *arg)
// {
//     printf("thread 1 returning ... \n");
//     int *p = (int *)malloc(sizeof(int));
//     *p = 1;
//     return (void *)p;
// }
// void *thread2(void *arg)
// {
//     printf("thread 2 exiting ...\n");
//     int *p = (int *)malloc(sizeof(int));
//     *p = 2;
//     pthread_exit((void *)p);
// }
// void *thread3(void *arg)
// {
//     while (1)
//     {
//         printf("thread 3 is running ...\n");
//         sleep(1);
//     }
//     return NULL;
// }
// int main(void)
// {
//     pthread_t tid;
//     void *ret;
//     // thread 1 return
//     pthread_create(&tid, NULL, thread1, NULL);
//     pthread_join(tid, &ret); // 等待任务完成
//     printf("thread return, thread id %X, return code:%d\n", tid, *(int *)ret);
//     free(ret);
//     // thread 2 exit
//     pthread_create(&tid, NULL, thread2, NULL);
//     pthread_join(tid, &ret);
//     printf("thread return, thread id %X, return code:%d\n", tid, *(int *)ret);
//     free(ret);
//     // thread 3 cancel by other
//     pthread_create(&tid, NULL, thread3, NULL);
//     sleep(3);
//     pthread_cancel(tid); // 关闭3进程
//     pthread_join(tid, &ret);
//     if (ret == PTHREAD_CANCELED)
//         printf("thread return, thread id %X, return code:PTHREAD_CANCELED\n", tid);
//     else
//         printf("thread return, thread id %X, return code:NULL\n", tid);
// }

// #include <stdio.h>
// #include <errno.h> // 使用宏 ESRCH
// #include <pthread.h>

// // 线程执行的函数
// void *ThreadFun(void *arg)
// {
//     pthread_exit("http://c.biancheng.net");
// }

// int main()
// {
//     int res;
//     void *thread_result;
//     pthread_t myThread;

//     // 创建 myThread 线程
//     res = pthread_create(&myThread, NULL, ThreadFun, NULL);
//     if (res != 0)
//     {
//         printf("线程创建失败");
//         return 0;
//     }

//     // 阻塞主线程，等待 myThread 线程执行结束
//     res = pthread_join(myThread, &thread_result);
//     if (res != 0)
//     {
//         printf("1：等待线程失败");
//     }

//     // 输出获取到的 myThread 线程的返回值
//     printf("%s\n", (char *)thread_result);

//     // 尝试再次获取 myThread 线程的返回值
//     res = pthread_join(myThread, &thread_result);
//     if (res == ESRCH)
//     {
//         printf("2：等待线程失败，线程不存在");
//     }
//     return 0;
// }

// #include <unistd.h>
// #include <stdlib.h>
// #include <stdio.h>
// #include <string.h>
// #include <pthread.h>
// void *rout(void *arg)
// {
//     int i;
//     pthread_t tid;
//     tid = pthread_self();
//     printf("%ld\n", tid);
//     for (;;)
//     {
//         printf("I'am thread 1\n");
//         sleep(1);
//     }
// }
// int main(void)
// {
//     pthread_t tid;
//     int ret;
//     if ((ret = pthread_create(&tid, NULL, rout, NULL)) != 0)
//     {
//         fprintf(stderr, "pthread_create : %s\n", strerror(ret));
//         exit(EXIT_FAILURE);
//     }

//     int i;
//     for (;;)
//     {
//         printf("I'am main thread\n");
//         sleep(1);
//     }
// }

// /* include/linux/mm_types.h */
// struct page
// {
//     /* 原⼦标志，有些情况下会异步更新 */
//     unsigned long flags;
//     union
//     {
//         struct
//         {
//             /* 换出⻚列表，例如由zone->lru_lock保护的active_list */
//             struct list_head lru;
//             /* 如果最低为为0，则指向inode
//              * address_space，或为NULL
//              * 如果⻚映射为匿名内存，最低为置位
//              * ⽽且该指针指向anon_vma对象
//              */
//             struct address_space *mapping;
//             /* 在映射内的偏移量 */
//             pgoff_t index;
//             /*
//              * 由映射私有，不透明数据
//              * 如果设置了PagePrivate，通常⽤于buffer_heads
//              * 如果设置了PageSwapCache，则⽤于swp_entry_t
//              * 如果设置了PG_buddy，则⽤于表⽰伙伴系统中的阶
//              */
//             unsigned long private;
//         };
//         struct
//         { /* slab, slob and slub */
//             union
//             {
//                 struct list_head slab_list; /* uses lru */
//                 struct
//                 { /* Partial pages */
//                     struct page *next;
// #ifdef CONFIG_64BIT
//                     int pages;    /* Nr of pages left */
//                     int pobjects; /* Approximate count */
// #else
//                     short int pages;
//                     short int pobjects;
// #endif
//                 };
//             };
//             struct kmem_cache *slab_cache; /* not slob */
//             /* Double-word boundary */
//             void *freelist; /* first free object */
//             union
//             {
//                 void *s_mem;            /* slab: first object */
//                 unsigned long counters; /* SLUB */
//                 struct
//                 {                        /* SLUB */
//                     unsigned inuse : 16; /* ⽤于SLUB分配器：对象的数⽬ */
//                     unsigned objects : 15;
//                     unsigned frozen : 1;
//                 };
//             };
//             ...
//         };
//         union
//         {
//             /* 内存管理⼦系统中映射的⻚表项计数，⽤于表⽰⻚是否已经映射，还⽤于限制逆向映射搜
//             索*/
//             atomic_t _mapcount;
//             unsigned int page_type;
//             unsigned int active; /* SLAB */
//             int units;           /* SLOB */
//         };
//         ...
// #if defined(WANT_PAGE_VIRTUAL)
//             /* 内核虚拟地址（如果没有映射则为NULL，即⾼端内存） */
//             void *virtual;
// #endif /* WANT_PAGE_VIRTUAL */
//         ...
//     }